import random
from itertools import chain
import os
import copy
from pynput import keyboard


class Game(object):
    def __init__(self, width=4, height=4, win_score=2048):
        """初始函数"""
        self.width = width
        self.height = height
        self.win_score = win_score
        self.max_score = 0
        self.score = 0

    def reset(self):
        """重置函数"""
        if self.score > self.max_score:
            self.max_score = self.score
        self.score = 0
        self.field = [[0 for j in range(self.width)] for i in range(self.height)]
        for i in range(self.random_count()):
            self.random_creat()

    def random_creat(self):
        """随机生成函数"""
        while True:
            firstIndex = random.choice(range(self.height))
            secondIndex = random.choice(range(self.width))
            if self.field[firstIndex][secondIndex] == 0:
                value = random.choice([2, 4, 2, 2, 2])
                self.field[firstIndex][secondIndex] = value
                break

    def random_count(self):
        """随机生成个数"""
        count = 0
        for i in range(self.height):
            for j in range(self.width):
                if self.field[i][j] == 0:
                    count += 1
        if count == 0:
            return 0
        elif count == 1:
            return 1
        else:
            return random.choice([1, 1, 2, 2, 1])

    def draw(self):
        """画棋盘"""
        print("分数：{0}  最高分:{1}".format(self.score, self.max_score))
        for i in range(self.height):
            print("+------" * 4 + "+")
            line = "|{0:^6}|{1:^6}|{2:^6}|{3:^6}|"
            print(line.format(self.field[i][0] if self.field[i][0] != 0 else "",
                              self.field[i][1] if self.field[i][1] != 0 else "",
                              self.field[i][2] if self.field[i][2] != 0 else "",
                              self.field[i][3] if self.field[i][3] != 0 else "", ))
        print("+------" * 4 + "+")
        if self.is_win():
            print("          游戏胜利！")
        elif self.is_gameover():
            print("          游戏失败！")
        else:
            print('(W)Up (S)Down (A)Left (D)Right')
        print('     (R)Restart (Q)Exit')

    def is_win(self):
        """判断游戏胜利"""
        return max(chain(*self.field)) >= self.win_score

    def is_gameover(self):
        """判断游戏失败"""
        if self.is_move_up() or self.is_move_down() or self.is_move_left() or self.is_move_right():
            return False
        else:
            return True

    def is_move_left(self):
        """判断能否左移"""
        for i in range(self.height):
            for j in range(self.width):
                if self.field[i][j] == 0:
                    return True
                if j != self.width - 1:
                    if self.field[i][j] == self.field[i][j + 1]:
                        return True
        return False

    def is_move_right(self):
        """判断能否右移"""
        for i in range(self.height):
            for j in range(self.width):
                if self.field[i][j] == 0:
                    return True
                if j != self.width - 1:
                    if self.field[i][j] == self.field[i][j + 1]:
                        return True
        return False

    def is_move_up(self):
        """判断能否上移"""
        for i in range(self.height):
            for j in range(self.width):
                if self.field[i][j] == 0:
                    return True
                if i != self.height - 1:
                    if self.field[i][j] == self.field[i + 1][j]:
                        return True
        return False

    def is_move_down(self):
        """判断能否下移"""
        for i in range(self.height):
            for j in range(self.width):
                if self.field[i][j] == 0:
                    return True
                if i != self.height - 1:
                    if self.field[i][j] == self.field[i + 1][j]:
                        return True
        return False

    def move_left(self):
        """左移"""
        # 移动（填补空位）
        for i in range(self.height):
            location = 0
            for j in range(self.width):
                if self.field[i][j] != 0:
                    self.field[i][location] = self.field[i][j]
                    if location != j:
                        self.field[i][j] = 0
                    location += 1
        # 合并
        for i in range(self.height):
            for j in range(self.width - 1):
                if self.field[i][j] == self.field[i][j + 1] and self.field[i][j] != 0:
                    self.field[i][j] = self.field[i][j] * 2
                    self.score += self.field[i][j]
                    for t in range(j + 1, self.width - 1):
                        self.field[i][t] = self.field[i][t + 1]
                    self.field[i][self.width - 1] = 0

    def move_right(self):
        """右移"""
        # 移动（填补空位）
        for i in range(self.height):
            location = self.width - 1
            for j in range(self.width - 1, -1, -1):
                if self.field[i][j] != 0:
                    self.field[i][location] = self.field[i][j]
                    if location != j:
                        self.field[i][j] = 0
                    location -= 1
        # 合并
        for i in range(self.height):
            for j in range(self.width - 1, 0, -1):
                if self.field[i][j] == self.field[i][j - 1] and self.field[i][j] != 0:
                    self.field[i][j] = self.field[i][j] * 2
                    self.score += self.field[i][j]
                    for t in range(j - 1, 0, -1):
                        self.field[i][t] = self.field[i][t - 1]
                    self.field[i][0] = 0

    def move_up(self):
        """上移"""
        # 移动（填补空位）
        for j in range(self.width):
            location = 0
            for i in range(self.height):
                if self.field[i][j] != 0:
                    self.field[location][j] = self.field[i][j]
                    if location != i:
                        self.field[i][j] = 0
                    location += 1
        # 合并
        for j in range(self.width):
            for i in range(self.height - 1):
                if self.field[i][j] == self.field[i + 1][j] and self.field[i][j] != 0:
                    self.field[i][j] = self.field[i][j] * 2
                    self.score += self.field[i][j]
                    for t in range(i + 1, self.height - 1):
                        self.field[t][j] = self.field[t + 1][j]
                    self.field[self.height - 1][j] = 0

    def move_down(self):
        """下移"""
        # 移动（填补空位）
        for j in range(self.width):
            location = self.height - 1
            for i in range(self.height - 1, -1, -1):
                if self.field[i][j] != 0:
                    self.field[location][j] = self.field[i][j]
                    if location != i:
                        self.field[i][j] = 0
                    location -= 1
        # 合并
        for j in range(self.width):
            for i in range(self.height - 1, 0, -1):
                if self.field[i][j] == self.field[i - 1][j] and self.field[i][j] != 0:
                    self.field[i][j] = self.field[i][j] * 2
                    self.score += self.field[i][j]
                    for t in range(i - 1, 0, -1):
                        self.field[t][j] = self.field[t - 1][j]
                    self.field[0][j] = 0


def main():
    game = Game(width=4, height=4, win_score=64)
    game.reset()
    game.draw()

    def on_press(key):
        try:
            if key.char == 'w' and game.is_win() == False and game.is_gameover() == False:
                if game.is_move_up():
                    field = copy.deepcopy(game.field)
                    game.move_up()
                    # 判断移动是否有效
                    if field != game.field:
                        for i in range(game.random_count()):
                            game.random_creat()
                    # 清空控制台
                    os.system('cls')
                    game.draw()
            elif key.char == 's' and game.is_win() == False and game.is_gameover() == False:
                if game.is_move_down():
                    field = copy.deepcopy(game.field)
                    game.move_down()
                    # 判断移动是否有效
                    if field != game.field:
                        for i in range(game.random_count()):
                            game.random_creat()
                    # 清空控制台
                    os.system('cls')
                    game.draw()
            elif key.char == 'a' and game.is_win() == False and game.is_gameover() == False:
                if game.is_move_left():
                    field = copy.deepcopy(game.field)
                    game.move_left()
                    # 判断移动是否有效
                    if field != game.field:
                        for i in range(game.random_count()):
                            game.random_creat()
                    # 清空控制台
                    os.system('cls')
                    game.draw()
            elif key.char == 'd' and game.is_win() == False and game.is_gameover() == False:
                if game.is_move_right():
                    field = copy.deepcopy(game.field)
                    game.move_right()
                    # 判断移动是否有效
                    if field != game.field:
                        for i in range(game.random_count()):
                            game.random_creat()
                    # 清空控制台
                    os.system('cls')
                    game.draw()
            elif key.char == 'r':
                # 清空控制台
                os.system('cls')
                game.reset()
                game.draw()
            elif key.char == 'q':
                listener.stop()
                # 退出cmd控制台
                os.system("taskkill /f /im cmd.exe")
        except AttributeError:
            pass

    # 键盘监听
    with keyboard.Listener(on_press=on_press) as listener:
        listener.join()


if __name__ == '__main__':
    main()
